package logic

import (
	"card/pkg/util"
	"context"
	"github.com/duke-git/lancet/v2/slice"
)

type PokersLogic struct {
	ctx context.Context
}

const (
	Single = iota + 1
	Double
	Straight       //顺子
	DoubleStraight //双顺
	TripleStraight //飞机
	Three          //三不带
	ThreeAndOne    //三带一
	ThreeAndTwo    //三代二
	Boom           //炸弹
	JokerBoom      //王炸
)

func (l *PokersLogic) ShuffleCards() ([]string, map[int][]string) {
	cards := []string{
		"a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
		"b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15",
		"c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12", "c13", "c14", "c15",
		"d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
		"e1", "e2",
	}
	item := ""
	cards = slice.Shuffle(cards)
	data := make(map[int][]string)
	i := 0
	for {
		if i > 16 {
			break
		}
		for j := 0; j < 3; j++ {
			cards, item = util.ArrayPop(cards)
			data[j] = append(data[j], item)
		}
		i++
	}
	return cards, data
}

func (l *PokersLogic) IsSingle(cards []string) bool {
	return len(cards) == 1
}

func (l *PokersLogic) IsDouble(cards []string) bool {
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(numberArr) == 2 {
		if numberArr[0] == numberArr[1] {
			return true
		}
	}
	return false
}

func (l *PokersLogic) IsStraight(cards []string) bool {
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(numberArr) < 5 || len(numberArr) > 12 {
		return false
	}
	if util.CheckHasJoker(cards) {
		return false
	}
	for i := 0; i < len(numberArr)-1; i++ {
		if numberArr[i] == 2 {
			return false
		}
		if numberArr[i+1]-numberArr[i] != 1 {
			return false
		}
	}
	return true
}

func (l *PokersLogic) IsDoubleStraight(cards []string) bool {
	if len(cards) < 6 || len(cards)%2 != 0 {
		return false
	}
	if util.CheckHasJoker(cards) {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	for i := 0; i < len(numberArr)-2; i += 2 {
		if numberArr[i] == 2 {
			return false
		}
		if numberArr[i+2]-numberArr[i] != 1 {
			return false
		}
	}
	return true
}

func (l *PokersLogic) IsTripleStraight(cards []string) bool {
	if len(cards) < 6 || len(cards)%3 != 0 {
		return false
	}
	if util.CheckHasJoker(cards) {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	if slice.Contain(numberArr, 2) {
		return false
	}
	if len(slice.Unique(numberArr)) != 2 {
		return false
	}
	return true
}

func (l *PokersLogic) IsThree(cards []string) bool {
	if len(cards) != 3 {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(slice.Unique(numberArr)) != 1 {
		return false
	}
	return true
}

func (l *PokersLogic) IsThreeAndOne(cards []string) bool {
	if len(cards) != 4 {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(slice.Unique(numberArr)) != 2 {
		return false
	}
	return true
}

func (l *PokersLogic) IsThreeAndTwo(cards []string) bool {
	if len(cards) != 5 {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(slice.Unique(numberArr)) != 2 {
		return false
	}
	return true
}

func (l *PokersLogic) IsBoom(cards []string) bool {
	if len(cards) != 4 {
		return false
	}
	numberArr := util.SliceSubstring2Int(cards, 0)
	if len(slice.Unique(numberArr)) != 1 {
		return false
	}
	return true
}

func (l *PokersLogic) IsJokerBoom(cards []string) bool {
	if len(cards) != 2 {
		return false
	}
	for i := 0; i < len(cards); i++ {
		str := cards[i]
		if str[0] != 'e' {
			return false
		}
	}
	return true
}

func (l *PokersLogic) CanOut(cards []string) (bool, int) {
	length := len(cards)
	can := false
	cardType := 0
	switch length {
	case 1:
		can = true
		cardType = Single
	case 2:
		if l.IsDouble(cards) {
			can = true
			cardType = Double
		}
		if l.IsJokerBoom(cards) {
			can = true
			cardType = JokerBoom
		}
	case 3:
		if l.IsThree(cards) {
			can = true
			cardType = Three
		}
	case 4:
		if l.IsThreeAndOne(cards) {
			can = true
			cardType = ThreeAndOne
		}
		if l.IsBoom(cards) {
			can = true
			cardType = Boom
		}
	case 5:
		if l.IsThreeAndTwo(cards) {
			can = true
			cardType = ThreeAndTwo
		}
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
	case 6:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
		if l.IsTripleStraight(cards) {
			can = true
			cardType = TripleStraight
		}
	case 7:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
	case 8:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
	case 9:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
		if l.IsTripleStraight(cards) {
			can = true
			cardType = TripleStraight
		}
	case 10:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
	case 11:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
	case 12:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
		if l.IsTripleStraight(cards) {
			can = true
			cardType = TripleStraight
		}
	case 14:
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
	case 15:
		if l.IsStraight(cards) {
			can = true
			cardType = Straight
		}
	case 16:
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
	case 18:
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
		if l.IsTripleStraight(cards) {
			can = true
			cardType = TripleStraight
		}
	case 20:
		if l.IsDoubleStraight(cards) {
			can = true
			cardType = DoubleStraight
		}
	}
	return can, cardType
}

func (l *PokersLogic) Compare(prevCards []string, myCards []string) bool {
	if len(prevCards) == 0 && len(myCards) != 0 {
		return true
	}
	//判断上家card的类型
	_, prevCardType := l.CanOut(prevCards)
	_, myCardType := l.CanOut(myCards)
	prevIntCards := util.SliceSubstring2Int(prevCards, 0)
	myIntCards := util.SliceSubstring2Int(myCards, 0)
	switch prevCardType {
	case Single, Double, Three, DoubleStraight, Straight:
		if myCardType == prevCardType && myIntCards[0] > prevIntCards[0] {
			return true
		}
		if myCardType == Boom || myCardType == JokerBoom {
			return true
		}
	case Boom:
		if myCardType == prevCardType && myIntCards[0] > prevIntCards[0] {
			return true
		}
		if myCardType == JokerBoom {
			return true
		}
	case ThreeAndTwo, ThreeAndOne:
		prevIntCards = util.GetCountNumber(prevIntCards, 3)
		myIntCards = util.GetCountNumber(myIntCards, 3)
		if myCardType == prevCardType && myIntCards[0] > prevIntCards[0] {
			return true
		}
	}
	return false
}
